home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / wnos / wn941101 / tcpsubr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-10  |  6.2 KB  |  301 lines

  1. /* Low level TCP routines:
  2.  *  control block management
  3.  *  sequence number logical operations
  4.  *  state transitions
  5.  *  RTT cacheing
  6.  *
  7.  * Copyright 1991 Phil Karn, KA9Q
  8.  */
  9. #include <stdio.h>
  10. #include "global.h"
  11. #include "timer.h"
  12. #include "mbuf.h"
  13. #include "netuser.h"
  14. #include "internet.h"
  15. #include "tcp.h"
  16. #include "ip.h"
  17.  
  18.  
  19. /* TCP connection states */
  20. char *Tcpstates[] = {
  21.     "",
  22.     "Closed",
  23.     "Listen",
  24.     "SYN sent",
  25.     "SYN rcvd",
  26.     "Established",
  27.     "FIN wait 1",
  28.     "FIN wait 2",
  29.     "Close wait",
  30.     "Last ACK",
  31.     "Closing",
  32.     "Time wait"
  33. };
  34.  
  35. /* TCP closing reasons */
  36. char *Tcpreasons[] = {
  37.     "Normal",
  38.     "Reset/Refused",
  39.     "Timeout",
  40.     "ICMP"
  41. };
  42.  
  43. struct tcb *Tcbs;
  44.  
  45. int16 Tcp_mss = DEF_MSS;    /* Maximum segment size to be sent with SYN */
  46. int32 Tcp_irtt = DEF_RTT;    /* Initial guess at round trip time */
  47. int Tcp_trace = 0;            /* State change tracing flag */
  48. int Tcp_syndata = 0;
  49. struct tcp_rtt Tcp_rtt[RTTCACHE];
  50.  
  51. struct mib_entry Tcp_mib[] = {
  52.     NULLCHAR,        0,
  53.     "RtoAlgorithm",    4,            /* Van Jacobsen's algorithm */
  54.     "RtoMin",        0,            /* No lower bound */
  55.     "RtoMax",        MAXINT32,    /* No upper bound */
  56.     "MaxConn",        -1L,        /* No limit */
  57.     "ActiveOpens",    0,
  58.     "PassiveOpens",    0,
  59.     "AttemptFails",    0,
  60.     "EstabResets",    0,
  61.     "CurrEstab",    0,
  62.     "InSegs",        0,
  63.     "OutSegs",        0,
  64.     "RetransSegs",    0,
  65.     NULLCHAR,        0,            /* Connection state goes here */
  66.     "InErrs",        0,
  67.     "OutRsts",        0,
  68. };
  69.  
  70. /* Look up TCP connection
  71.  * Return TCB pointer or NULLTCB if nonexistant.
  72.  * Also move the entry to the top of the list to speed future searches.
  73.  */
  74. struct tcb *
  75. lookup_tcb(conn)
  76. struct connection *conn;
  77. {
  78.     struct tcb *tcb, *tcblast = NULLTCB;
  79.     for(tcb=Tcbs; tcb != NULLTCB; tcblast = tcb, tcb = tcb->next){
  80.         /* Yet another structure compatibility hack */
  81.         if(conn->remote.port == tcb->conn.remote.port
  82.          && conn->local.port == tcb->conn.local.port
  83.          && conn->remote.address == tcb->conn.remote.address
  84.          && conn->local.address == tcb->conn.local.address){
  85.             if(tcblast != NULLTCB){
  86.                 /* Move to top of list */
  87.                 tcblast->next = tcb->next;
  88.                 tcb->next = Tcbs;
  89.                 Tcbs = tcb;
  90.             }
  91.             return tcb;
  92.         }
  93.     }
  94.     return NULLTCB;
  95. }
  96.  
  97. /* Create a TCB, return pointer. Return pointer if TCB already exists. */
  98. struct tcb *
  99. create_tcb(conn)
  100. struct connection *conn;
  101. {
  102.     struct tcb *tcb;
  103.     struct tcp_rtt *tp;
  104.  
  105.     if((tcb = lookup_tcb(conn)) != NULLTCB)
  106.         return tcb;
  107.     tcb = (struct tcb *)mxallocw(sizeof (struct tcb));
  108.     ASSIGN(tcb->conn,*conn);
  109.     tcb->state = TCP_CLOSED;
  110.     tcb->cwind = tcb->mss = Tcp_mss;
  111.     tcb->ssthresh = 65535L;
  112.     if((tp = rtt_get(tcb->conn.remote.address)) != NULLRTT){
  113.         tcb->srtt = tp->srtt;
  114.         tcb->mdev = tp->mdev;
  115.     } else {
  116.         tcb->srtt = Tcp_irtt;    /* mdev = 0 */
  117.     }
  118.     /* Initialize timer intervals */
  119.     set_timer(&tcb->timer,tcb->srtt);
  120.     tcb->timer.func = tcp_timeout;
  121.     tcb->timer.arg = tcb;
  122.  
  123.     tcb->next = Tcbs;
  124.     Tcbs = tcb;
  125.     return tcb;
  126. }
  127.  
  128. /* Close our TCB */
  129. void
  130. close_self(tcb,reason)
  131. struct tcb *tcb;
  132. int reason;
  133. {
  134.     struct reseq *rp, *rp1;
  135.  
  136.     if(tcb == NULLTCB)
  137.         return;
  138.  
  139.     stop_timer(&tcb->timer);
  140.     tcb->reason = reason;
  141.  
  142.     /* Flush reassembly queue; nothing more can arrive */
  143.     for(rp = tcb->reseq;rp != NULLRESEQ;rp = rp1){
  144.         rp1 = rp->next;
  145.         free_p(rp->bp);
  146.         xfree((char *)rp);
  147.     }
  148.     tcb->reseq = NULLRESEQ;
  149.     setstate(tcb,TCP_CLOSED);
  150. }
  151.  
  152. /* Sequence number comparisons
  153.  * Return true if x is between low and high inclusive,
  154.  * false otherwise
  155.  */
  156. int
  157. seq_within(int32 x,int32 low,int32 high)
  158. {
  159.     if(low <= high){
  160.         if(low <= x && x <= high)
  161.             return 1;
  162.     } else {
  163.         if(low >= x && x >= high)
  164.             return 1;
  165.     }
  166.     return 0;
  167. }
  168.  
  169. int
  170. seq_lt(int32 x,int32 y)
  171. {
  172.     return (long)(x-y) < 0;
  173. }
  174.  
  175. int
  176. seq_le(int32 x,int32 y)
  177. {
  178.     return (int)(x-y) <= 0;
  179. }
  180.  
  181. int
  182. seq_gt(int32 x,int32 y)
  183. {
  184.     return (long)(x-y) > 0;
  185. }
  186.  
  187. int
  188. seq_ge(int32 x,int32 y)
  189. {
  190.     return (long)(x-y) >= 0;
  191. }
  192.  
  193. void
  194. setstate(struct tcb *tcb,int newstate)
  195. {
  196.     char oldstate = tcb->state;
  197.  
  198.     tcb->state = newstate;
  199.     if(Tcp_trace)
  200.         tprintf("TCB %lx %s -> %s\n",ptol(tcb),
  201.          Tcpstates[oldstate],Tcpstates[newstate]);
  202.  
  203.     /* Update MIB variables */
  204.     switch(oldstate){
  205.     case TCP_CLOSED:
  206.         if(newstate == TCP_SYN_SENT)
  207.             tcpActiveOpens++;
  208.         break;
  209.     case TCP_LISTEN:
  210.         if(newstate == TCP_SYN_RECEIVED)
  211.             tcpPassiveOpens++;
  212.         break;
  213.     case TCP_SYN_SENT:
  214.         if(newstate == TCP_CLOSED)
  215.             tcpAttemptFails++;
  216.         break;
  217.     case TCP_SYN_RECEIVED:
  218.         switch(newstate){
  219.         case TCP_CLOSED:
  220.         case TCP_LISTEN:
  221.             tcpAttemptFails++;
  222.         break;
  223.         }
  224.         break;
  225.     case TCP_ESTABLISHED:
  226.     case TCP_CLOSE_WAIT:
  227.         switch(newstate){
  228.         case TCP_CLOSED:
  229.         case TCP_LISTEN:
  230.             tcpEstabResets++;    
  231.         break;
  232.         }
  233.         tcpCurrEstab--;
  234. // dl8yq
  235. bbsUsers--;
  236.         break;
  237.     }
  238.     if(newstate == TCP_ESTABLISHED || newstate == TCP_CLOSE_WAIT){
  239.         tcpCurrEstab++;
  240. // dl8yq
  241. bbsUsers++;
  242.         }
  243.     if(tcb->s_upcall)
  244.         (*tcb->s_upcall)(tcb,oldstate,newstate);
  245.  
  246.     switch(newstate){
  247.     case TCP_SYN_RECEIVED:    /***/
  248.     case TCP_ESTABLISHED:
  249.         /* Notify the user that he can begin sending data */
  250.         if(tcb->t_upcall)
  251.             (*tcb->t_upcall)(tcb,tcb->window - tcb->sndcnt);
  252.         break;
  253.     }
  254. }
  255.  
  256. /* Round trip timing cache routines.
  257.  * These functions implement a very simple system for keeping track of
  258.  * network performance for future use in new connections.
  259.  * The emphasis here is on speed of update (rather than optimum cache hit
  260.  * ratio) since rtt_add is called every time a TCP connection updates
  261.  * its round trip estimate.
  262.  */
  263. void
  264. rtt_add(addr,rtt)
  265. int32 addr;        /* Destination IP address */
  266. int32 rtt;
  267. {
  268.     struct tcp_rtt *tp;
  269.     int32 abserr;
  270.  
  271.     if(addr == 0)
  272.         return;
  273.  
  274.     tp = &Tcp_rtt[(unsigned short)addr % RTTCACHE];
  275.  
  276.     if(tp->addr != addr){
  277.         /* New entry */
  278.         tp->addr = addr;
  279.         tp->srtt = rtt;
  280.         tp->mdev = 0;
  281.     } else {
  282.         /* Run our own SRTT and MDEV integrators, with rounding */
  283.         abserr = (rtt > tp->srtt) ? rtt - tp->srtt : tp->srtt - rtt;
  284.         tp->srtt = ((AGAIN-1)*tp->srtt + rtt + (AGAIN/2)) >> LAGAIN;
  285.         tp->mdev = ((DGAIN-1)*tp->mdev + abserr + (DGAIN/2)) >> LDGAIN;
  286.     }
  287. }
  288.  
  289. struct tcp_rtt *
  290. rtt_get(int32 addr)
  291. {
  292.     struct tcp_rtt *tp;
  293.  
  294.     if(addr == 0)
  295.         return NULLRTT;
  296.  
  297.     tp = &Tcp_rtt[(unsigned short)addr % RTTCACHE];
  298.     return (tp->addr != addr) ? NULLRTT : tp;
  299. }
  300.  
  301.